package org.ece.meteo.eventH;

import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.osgi.service.event.EventAdmin;
import org.osgi.util.tracker.ServiceTracker;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;


public class EventHandlerImpl implements EventHandler{
	String unit;
	ServiceTracker tracker;
	EventAdmin ea;
	static final String path = "org/ece/meteo/alerte/1";
	static final int ok		= 0;
	static final int hTemp 	= 1;
	static final int hWind 	= 2;
	static final int hHydro = 3;
	static final int lTemp 	= 4;
	int temp, hydro, wind;	// this will store if alert has already been sent, 'ok' is none.
	double tmp;
	static final String servlet_url = "http://localhost:8080/servlet/meteo";
	static boolean isServlet;	// Servlet is running?
	static long first; 			// First try (time)
	
	public EventHandlerImpl() {
		temp = ok;
		wind = ok;
		hydro = ok;
		isServlet = true;
		first = System.currentTimeMillis();

		// Open a service tracker
		tracker = new ServiceTracker(Activator.BC, EventAdmin.class.getName(), null);
		tracker.open();
		ea = (EventAdmin) tracker.getService();
	}
	
	/**
	 * Implements EventHandlerImpl.handleEvent(). 
	 * Check events coming from sensors, their values and
	 * send new event according to the alert type.
	 * @param event the event read from the service tracker.
	**/
	 public void handleEvent(Event event){
	    String reportTitle 	= (String) event.getProperty("title");
	    String reportPath 	= (String) event.getProperty("path");
	    String reportTime 	= (String) event.getProperty("time");
	    String reportData 	= (String) event.getProperty("data");
	    
	    if(reportTitle != null){
	    	
	    	// Read temperature events
	    	if(reportPath.contains("Temp")){
	    		unit = "°C";
	    		tmp = Double.parseDouble(reportData.replace(',', '.'));	// Because parseDouble don't really like the french notation...
	    		if((tmp > 35) && (temp != hTemp)){
	    			temp = hTemp;
	    			sendAlert(hTemp, "High temperature reached!!");
	    		}else if ((tmp < 5) && (temp != lTemp)){
	    			temp = lTemp;
	    			sendAlert(hTemp, "Low temperature reached!!");
	    		}else if ((temp != ok) && (tmp > 6) && (tmp < 31)){
	    			temp = ok;
	    			sendAlert(hTemp, "temperature is now correct");
	    		}

		    // Read wind events
	    	}else if(reportPath.contains("Vent")){
	    		unit = " noeuds";
	    		tmp = Double.parseDouble(reportData.replace(',', '.'));	// Because parseDouble don't really like the french notation...
	    		if((tmp >  (double) 33) && (wind != hWind)){
	    			wind = hWind;
	    			sendAlert(hWind, "A storm is coming!!");
	    		}else if((tmp <  (double) 29) && (wind == hWind)){
	    			wind = ok;
	    			sendAlert(hWind, "end of storm");
	    		}

		    // Read hydro events
		    }else if(reportPath.contains("Hydro")){
		    		unit = " mm";
		    		if((Integer.parseInt(reportData) > 100) && (hydro != hHydro)){
		    			hydro = hHydro;
		    			sendAlert(hHydro, "flooding is here!");
		    		}else if((Integer.parseInt(reportData) < 90) && (hydro == hHydro)){
		    			hydro = ok;
		    			sendAlert(hHydro, "end flooding");
		    		}
		 	}else
		    	System.out.println("---- unknown event => " + reportPath);
	    	
	    	// Now, print out the event received
	    	System.out.println("[" + reportTime + "]\t" + reportTitle + " à " + reportData + unit);
	    }
	}
	 
		/**
		 * Implements EventHandlerImpl.sendAlert(). 
		 * Sends an asynchronous event alert.
		 * @param type the alert type.
		 * @param message the alert message.
		**/
	 private void sendAlert(int type, String message){
		try {
			//System.out.println("Alerte ! " + type + " " + message);
			if (ea != null) {
				Dictionary props = new Hashtable();
				props.put("title", "Alert 1");
				props.put("path" , path);
				props.put("time", String.valueOf(System.currentTimeMillis()));
				props.put("data", "! " + message);
				props.put("type", String.valueOf(type));
				
				
				// post asynchronous event
				Event event = new Event(path, props);
				ea.postEvent(event);		
		    	//System.out.println("-event sent; isServlet = " + isServlet);	
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		/* if servlet is running, send GET message! */
		if(isServlet){
			sendGetRequest(servlet_url, message.replace(" ", "_"));	 	// replace space to display sentence as 1 argument
			//sendGetRequest(servlet_url, message+"?time="+time);		// better would be to send the original time.
		}else{ // if the servlet was not running (or not accessible), time to time try again
			if((System.currentTimeMillis() - first) > 35000 ){	// 35s already spent
				isServlet = true;	// Try again for the next alert
				System.out.println("!! GET request reactivated");
			}
		}
		
	}

		/**
		 * Implements EventHandlerImpl.sendGetRequest(). 
		 * Sends an asynchronous event alert. If the serlvet could not be accessed,
		 * GET request are deactivated for 35s.
		 * @param endpoint the servlet url String.
		 * @param requestParameters the parameters to be sent as String.
		**/
	public static String sendGetRequest(String endpoint, String requestParameters){
		String result = null;
		requestParameters = "alert=" + requestParameters;
		if (endpoint.startsWith("http://"))	{
			try	{
				// Construct data
				StringBuffer data = new StringBuffer();

				// Send data
				String urlStr = endpoint;
				if (requestParameters != null && requestParameters.length () > 0)				{
					urlStr += "?" + requestParameters;
				}
		    	System.out.println(">> alert sent to servlet : " + urlStr);
				URL url = new URL(urlStr);
				URLConnection conn = url.openConnection ();
			
				// Get the response
				BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
				StringBuffer sb = new StringBuffer();
				String line;
				while ((line = rd.readLine()) != null)	{
					sb.append(line);
				}
				rd.close();
				result = sb.toString();
			} catch (Exception e){
				isServlet = false;		// The servlet was not reached, don't try to send new request for next 35s.
				//e.printStackTrace(); // It works, don't need it anymore :) 
		    	System.out.println("!! could not access the servlet - GET request disabled for 35s");
			}
		}
		return result;
	}	
	
}
